package models

import (
	"cubeAdmin/common/utils"
	"cubeAdmin/vo/menu"
	"github.com/beego/beego/v2/client/orm"
	"github.com/beego/beego/v2/core/logs"
)

type SysMenu struct {
	Id            int64     `json:"id"`
	Name          string    `json:"name" valid:"Required;"`
	IFrame        int8      `json:"iframe"`
	Component     string    `json:"component"`
	ParentId      int64     `json:"parentId"`
	Sort          int32     `json:"sort"`
	Icon          string    `json:"icon"`
	Path          string    `json:"path"`
	Cache         int8      `json:"cache"`
	Title         string    `orm:"-" json:"title"`
	NoCache       bool      `orm:"-" json:"noCache"`
	Href          string    `orm:"-" json:"href"`
	Hidden        int8      `json:"hidden"`
	ComponentName string    `json:"componentName"`
	Permission    string    `json:"permission"`
	Type          int32     `json:"type"`
	Router        string    `json:"router"`
	RouterMethod  string    `json:"routerMethod"`
	Children      []SysMenu `json:"children" orm:"-"`
	Label         string    `orm:"-" json:"label"`
	CheckArr      string    `orm:"-" json:"checkArr"`
	BaseModel
}

func init() {
	orm.RegisterModel(new(SysMenu))
}

// GetMenuById retrieves SysMenu by Id. Returns error if
// Id doesn't exist
func GetMenuById(id int64) (v *SysMenu, err error) {
	o := orm.NewOrm()
	v = &SysMenu{Id: id}
	if err = o.Read(v); err == nil {
		return v, nil
	}
	return nil, err
}

func SelectMenuList(name string) []SysMenu {
	var menus []SysMenu
	o := orm.NewOrm()
	qs := o.QueryTable("sys_menu").Filter("is_del", 0)
	if name != "" {
		qs = qs.Filter("name", name)
	}
	qs.All(&menus)
	return menus
}

func GetAllMenus(name string) []SysMenu {
	var menus []SysMenu
	o := orm.NewOrm()
	qs := o.QueryTable("sys_menu").Filter("is_del", 0)
	if name != "" {
		qs = qs.Filter("name", name)
	}

	qs.All(&menus)
	return RecursionMenuList(menus, 0)
}

// 递归函数
func RecursionMenuList(data []SysMenu, pid int64) []SysMenu {
	var listTree = make([]SysMenu, 0)
	for _, value := range data {
		value.Label = value.Name
		if value.ParentId == pid {
			value.Children = RecursionMenuList(data, value.Id)
			listTree = append(listTree, value)
		}
	}
	return listTree
}

func AddMenu(m *SysMenu) (id int64, err error) {
	o := orm.NewOrm()
	id, err = o.Insert(m)
	return
}

func UpdateByMenu(m *SysMenu) (err error) {
	o := orm.NewOrm()
	_, err = o.Update(m)
	return
}

func DelByMenu(ids []int64) (err error) {
	str := utils.ReturnQ(len(ids))
	logs.Info(str)
	o := orm.NewOrm()
	_, err = o.Raw("UPDATE sys_menu SET is_del = ? WHERE id in("+str+")", 1, ids).Exec()
	return
}

// 获取权限string
func FindByRouterAndMethod(url string, method string) (permission string) {
	o := orm.NewOrm()
	var menu SysMenu
	err := o.QueryTable(new(SysMenu)).Filter("router", url).Filter("router_method", method).One(&menu)
	if err != nil {
		return ""
	}
	return menu.Permission
}

func BuildMenus(uid int64) []menu.MenusVo {
	o := orm.NewOrm()
	var lists orm.ParamsList
	_, err := o.Raw("SELECT r.* FROM sys_role r, sys_user_role u "+
		"WHERE r.id = u.role_id AND u.user_id = ?", uid).ValuesFlat(&lists, "id")
	if err != nil {
		logs.Error(err)
	}
	idsStr := utils.Convert(lists)
	logs.Info(idsStr)
	var menus []SysMenu
	_, e := o.Raw("select m.* from sys_menu m LEFT OUTER JOIN sys_role_menu t on m.id= t.menu_id "+
		"LEFT OUTER JOIN sys_role r on r.id = t.role_id where m.is_del=0 and m.hidden=0 and m.type!=2 and r.id in (?)",
		idsStr).QueryRows(&menus)

	if e != nil {
		logs.Error(e)
	}

	return buildMenus(buildTree(menus))

}

// GetMenusByUid 根据用户id查询菜单列表
func GetMenusByUid(uid int64) []SysMenu {
	o := orm.NewOrm()
	var lists orm.ParamsList
	_, err := o.Raw("SELECT r.* FROM sys_role r, sys_user_role u "+
		"WHERE r.id = u.role_id AND u.user_id = ?", uid).ValuesFlat(&lists, "id")
	if err != nil {
		logs.Error(err)
	}
	idsStr := utils.Convert(lists)
	logs.Info(idsStr)
	var menus []SysMenu
	_, e := o.Raw("select m.* from sys_menu m LEFT OUTER JOIN sys_role_menu t on m.id= t.menu_id "+
		"LEFT OUTER JOIN sys_role r on r.id = t.role_id where m.is_del=0 and m.hidden=0 and m.type!=2 and r.id in (?)",
		idsStr).QueryRows(&menus)

	if e != nil {
		logs.Error(e)
	}

	return menus
}

func buildTree(menus []SysMenu) []SysMenu {
	var trees []SysMenu
	for _, menu := range menus {
		if menu.ParentId == 0 {
			trees = append(trees, menu)
		}
	}

	for k, tree := range trees {
		var child []SysMenu
		for _, it := range menus {
			if it.ParentId == tree.Id {
				child = append(child, it)
			}
		}
		trees[k].Children = child
	}

	return trees

}

func buildMenus(menus []SysMenu) []menu.MenusVo {
	var list []menu.MenusVo
	for _, menuO := range menus {
		menuList := menuO.Children
		var vo = new(menu.MenusVo)

		if menuO.ComponentName != "" {
			vo.Name = menuO.ComponentName
		} else {
			vo.Name = menuO.Name
		}
		if menuO.ParentId == 0 {
			vo.Path = "/" + menuO.Path
		} else {
			vo.Path = menuO.Path
		}
		vo.Hidden = menuO.Hidden
		vo.Type = menuO.Type
		vo.Id = menuO.Id
		vo.ParentId = menuO.ParentId
		//vo.Router = menuO.Router
		vo.Href = menuO.Router

		//判断不是外链
		if menuO.IFrame == 0 {
			if menuO.ParentId == 0 {
				if menuO.Component == "" {
					vo.Component = "Layout"
				} else {
					vo.Component = menuO.Component
				}
			} else if menuO.Component != "" {
				vo.Component = menuO.Component
			}
		}

		vo.Title = menuO.Name
		vo.Icon = menuO.Icon
		vo.NoCache = !utils.IntToBool(menuO.Cache)
		//vo.Meta = menu.MenusMetaVo{Title: menuO.Name, Icon: menuO.Icon, NoCache: !utils.IntToBool(menuO.Cache)}

		if len(menuList) > 0 {
			vo.AlwaysShow = true
			vo.Redirect = "noredirect"
			vo.Children = buildMenus(menuList)
		} else if menuO.ParentId == 0 {
			var vo1 = new(menu.MenusVo)
			//vo1.Meta = vo.Meta
			if menuO.IFrame == 0 {
				vo1.Path = "index"
				vo1.Name = vo.Name
				vo1.Component = vo.Component
			} else {
				vo1.Path = menuO.Path
			}
			vo.Name = ""
			//vo.Meta = menu.MenusMetaVo{}
			vo.Component = "Layout"
			var list1 []menu.MenusVo
			list1 = append(list1, *vo1)
			vo.Children = list1
		}

		list = append(list, *vo)

	}

	return list
}
